﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FluentAssertions;
using O1.Kernel.Storage;
using O1.Kernel.Storage.Transactions;

namespace Tests.O1.Kernel.Storage
{
    [TestClass]
    public class MultiVersionScavengeStrategyTests
    {
        [TestMethod, TestCategory("Unit Test")]
        public void MultiVersionScavengeStrategyNextIdReturns0WhenLimitIs0()
        {
            ulong lastCommitted;
            var subject = new MultiVersionScavenger();
            subject.NextTarget(out lastCommitted).Should().Be(0);
            subject.NextTarget(out lastCommitted).Should().Be(0);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void MultiVersionScavengeStrategyNextIdCyclesOnceBoundsAreExceeded()
        {
            ulong lastCommitted;
            var subject = new MultiVersionScavenger();
            subject.RaiseBounds(5);
            subject.NextTarget(out lastCommitted).Should().Be(0);
            subject.NextTarget(out lastCommitted).Should().Be(1);
            subject.NextTarget(out lastCommitted).Should().Be(2);
            subject.NextTarget(out lastCommitted).Should().Be(3);
            subject.NextTarget(out lastCommitted).Should().Be(4);
            subject.NextTarget(out lastCommitted).Should().Be(0);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void MultiVersionScavengeStrategySetLastCommittedResultsInLastCommittedAsOutput()
        {
            ulong lastCommitted;
            var subject = new MultiVersionScavenger();
            subject.NextTarget(out lastCommitted);
            lastCommitted.Should().Be(TxExtensions.MinCommittedId);

            var txId = ((ulong)23).EmbedStatus(TxStatus.Committed);
            subject.SetLastCommittedTx(txId);
            subject.NextTarget(out lastCommitted); 
            lastCommitted.Should().Be(txId);
        }

        [TestMethod, TestCategory("Unit Test")]
        public void MultiVersionScavengeStrategySetLastCommittedOnlyIncreases()
        {
            ulong lastCommitted;
            var subject = new MultiVersionScavenger();
            var txId1 = ((ulong)23).EmbedStatus(TxStatus.Committed);
            subject.SetLastCommittedTx(txId1);
            subject.NextTarget(out lastCommitted);
            lastCommitted.Should().Be(txId1);

            var txId2 = ((ulong)22).EmbedStatus(TxStatus.Committed);
            subject.SetLastCommittedTx(txId2);
            subject.NextTarget(out lastCommitted);
            lastCommitted.Should().Be(txId1);
        }
    }
}
